#include "CH58x_common.h"
#include "stdint.h"
#include "stdio.h"
#include "DevicesADC.h"


__aligned(4) static uint16_t st_usADCDmaDatas[ADC0_SAMPLING_NUMBER][ADC0_SAMPLING_CHANNEL] = {0};


static void vAdcDmaInit(void)
{
    // /* 设置连续的周期 */
    // R8_ADC_AUTO_CYCLE = 193;

    /* 扫描通道设置（通道0，在R8_ADC_CHANNEL寄存器设置） */
    R32_ADC_SCAN_CFG1 = (ADC_CHANNEL_CURRENT_OUT << 0);

    /* 扫描选择ADC模块、当前通道扫描结束后，立即关闭当前通道、禁止中断、扫描通道数量 */
    R32_ADC_SCAN_CFG2 = RB_ADC_SCAN_SEL | RB_ADC_SCAN_MASK_DIS | ((ADC0_SAMPLING_CHANNEL - 1) << 24);

    /* 内存起始地址 */
    R32_ADC_DMA_BEG = (uint32_t)st_usADCDmaDatas;

    /* 内存结束地址 */
    R32_ADC_DMA_END = (uint32_t)st_usADCDmaDatas + sizeof(st_usADCDmaDatas);

    /* 清除ADC_DMA中断标志 */
    R8_ADC_DMA_IF = 0;

    /* 使能DMA、使能地址循环、禁止中断、连续触发、使能连续ADC */
    R8_ADC_CTRL_DMA = RB_ADC_DMA_ENABLE | RB_ADC_DMA_LOOP | RB_SCAN_AUTO_TYPE | RB_ADC_CONT_EN;
}

void vADCInit(void)
{
    GPIOA_ModeCfg(GPIO_Pin_4, GPIO_ModeIN_Floating);
    GPIOA_ModeCfg(GPIO_Pin_5, GPIO_ModeIN_Floating);

    /* 关闭 TKEY */
    R8_TKEY_CFG &= ~RB_TKEY_PWR_ON;

    /* 使能ADC、关闭缓冲器、单端输入、正常模式、0db增益、时钟频率 */
    R8_ADC_CFG = RB_ADC_POWER_ON | (ADC_PGA_0 << 4) | (SampleFreq_8_or_4 << 6);

    /* 采样周期：7*Tadc */
    R8_ADC_CONVERT = ADC0_SAMPLE_TIME;

    /* 采样通道 */
    R8_ADC_CHANNEL = ADC_CHANNEL_VOLTAGE_OUT;

    /* 使能内部温度传感器通道 */
    R8_TEM_SENSOR = RB_TEM_SEN_PWR_ON;

    /* 校准 */
    // ADC_DataCalib_Rough();

    vAdcDmaInit();

    /* 清除全部中断标志 */
    R8_ADC_INT_FLAG = 0;

    ADC_StartUp();
}

/*!
    \brief      ADC dma channel
    \param[in]  none
    \param[out] none
    \retval     none
*/
float fADCGetDMAValue(AdcDmaChannelEnum enumChannel)
{
#if (ADC0_SAMPLING_NUMBER < 3)
    return ((int32_t)st_usADCDmaDatas[0][enumChannel] * (3.3f / 4095.0f));

#else
    uint32_t uiValueSum = 0;
    uint16_t *pDatasHand = &st_usADCDmaDatas[0][enumChannel];
    uint16_t usValueMax = 0, usValueMin = 0xFFFF, usValueNow, i;

    if(enumChannel > ADC0_SAMPLING_CHANNEL)
        return 0.0f;

    for(i = 0; i < ADC0_SAMPLING_NUMBER; ++i, pDatasHand += ADC0_SAMPLING_CHANNEL)
    {
        usValueNow  = *pDatasHand;
        uiValueSum += usValueNow;

        /* 找到最大与最小值 */
        usValueMax = (usValueMax < usValueNow) ? usValueNow : usValueMax;
        usValueMin = (usValueMin > usValueNow) ? usValueNow : usValueMin;
    }

    uiValueSum -= usValueMax + usValueMin;

    return ((float)uiValueSum / (ADC0_SAMPLING_NUMBER - 2) * (3.3f / 4095.0f));

#endif
}

int32_t iADCGetDMAValue(AdcDmaChannelEnum enumChannel)
{
#if (ADC0_SAMPLING_NUMBER < 3)
    return ((int32_t)st_usADCDmaDatas[0][enumChannel] * 3300) / 4095;

#else
    uint32_t uiValueSum = 0;
    uint16_t *pDatasHand = &st_usADCDmaDatas[0][enumChannel];
    uint16_t usValueMax = 0, usValueMin = 0xFFFF, usValueNow, i;

    if(enumChannel > ADC0_SAMPLING_CHANNEL)
        return 0.0f;

    for(i = 0; i < ADC0_SAMPLING_NUMBER; ++i, pDatasHand += ADC0_SAMPLING_CHANNEL)
    {
        usValueNow  = *pDatasHand;
        uiValueSum += usValueNow;

        /* 找到最大与最小值 */
        usValueMax = (usValueMax < usValueNow) ? usValueNow : usValueMax;
        usValueMin = (usValueMin > usValueNow) ? usValueNow : usValueMin;
    }

    uiValueSum -= usValueMax + usValueMin;

    return (uiValueSum * 3300) / (4095 * (ADC0_SAMPLING_NUMBER - 2));

#endif
}

/*!
    \brief      ADC channel sample
    \param[in]  none
    \param[out] none
    \retval     none
*/
float fADCGetChannelValue(uint8_t channel, uint32_t uiCnt)
{
    uint32_t uiValueSum = 0, i;
    uint16_t usValueMax = 0, usValueMin = 0xFFFF, usValueNow;

    /* ADC regular channel config */
    ADC_ChannelCfg(channel);

    /* 切换通道后，丢弃第一次转换的数据 */
    ADC_ExcutSingleConver();

    for(i = 0; i < uiCnt; ++i)
    {
        usValueNow = ADC_ExcutSingleConver();
        uiValueSum += usValueNow;;

        /* 找到最大与最小值 */
        usValueMax = (usValueMax < usValueNow) ? usValueNow : usValueMax;
        usValueMin = (usValueMin > usValueNow) ? usValueNow : usValueMin;
    }

    /* 去除最大与最小值 */
    uiValueSum -= (usValueMax + usValueMin);

    return ((float)uiValueSum / (uiCnt - 2) * (3.3f / 4095.0f));
}

/*!
    \brief      ADC channel sample
    \param[in]  none
    \param[out] none
    \retval     none
*/
int32_t iADCGetChannelValue(uint8_t channel, uint32_t uiCnt)
{
    uint32_t uiValueSum = 0, i;
    uint16_t usValueMax = 0, usValueMin = 0xFFFF, usValueNow;

    /* ADC regular channel config */
    ADC_ChannelCfg(channel);

    /* 切换通道后，丢弃第一次转换的数据 */
    ADC_ExcutSingleConver();

    for(i = 0; i < uiCnt; ++i)
    {
        usValueNow = ADC_ExcutSingleConver();
        uiValueSum += usValueNow;;

        /* 找到最大与最小值 */
        usValueMax = (usValueMax < usValueNow) ? usValueNow : usValueMax;
        usValueMin = (usValueMin > usValueNow) ? usValueNow : usValueMin;
    }

    /* 去除最大与最小值 */
    uiValueSum -= (usValueMax + usValueMin);

    return (uiValueSum * 3300) / (4095 * (uiCnt - 2));
}
